---
description: Learn how to setup user auth for your Triplit application.
---

import { Steps, Callout, Tabs, Tab } from 'nextra/components';

# Authentication

In this guide we'll show you how to identify users connecting to your Triplit server and how to model access control with that information. By the end of the guide, you'll be able to define a schema that allows users to insert and update their own data, but not other users' data:

```typescript filename="schema.ts"
export const schema = S.Collections({
  blogPosts: {
    schema: S.Schema({
      id: S.Id(),
      title: S.String(),
      content: S.String(),
      authorId: S.String(),
    }),
    permissions: {
      authenticated: {
        read: { filter: [true] },
        insert: { filter: ['authorId', '=', '$token.sub'] },
        update: { filter: ['authorId', '=', '$token.sub'] },
        postUpdate: { filter: ['authorId', '=', '$token.sub'] },
        delete: { filter: ['authorId', '=', '$token.sub'] },
      },
    },
  },
});
```

<Steps>

### Choose an authentication provider

You'll likely start out your project using the `anon` and `service` tokens provided by default. These are great for getting started, but don't provide any user-specific information that you'll need to model access control.

Choose from one of the many authentication providers that issue JWTs:

- [Clerk](https://clerk.com/): read the Triplit integration guide [here](/auth/integration-guides/clerk)
- [Supabase](https://supabase.com/): read the Triplit integration guide [here](/auth/integration-guides/supabase)
- [Auth0](https://auth0.com/)
- [Amazon Cognito](https://aws.amazon.com/cognito/)
- ...or any other provider that issues JWTs

### Allow your Triplit server to verify JWTs

If you're using a third-party authentication provider, you'll need to provide the public key or secret that it's using to sign JWTs to your Triplit server so it can verify them. Triplit supports both symmetric (e.g. HMAC) and asymmetric (e.g. RSA) JWT encryption algorithms.

If you're connecting to a `triplit.io` URL, [you can use the dashboard](https://www.triplit.dev/docs/triplit-cloud/managed-machines#use-the-dashboard). If you're fully self-hosting Triplit (and _not_ pointed at a `triplit.io` URL), you'll need to set the `EXTERNAL_JWT_SECRET` environmental variable to the public key or symmetric secret.

### Pass the token to Triplit

Once you have your authentication provider set up in your app and your user is signed in, you'll need to pass the JWT to Triplit. This is done by calling `startSession` on the `TriplitClient` instance.

```typescript
import { TriplitClient } from '@triplit/client';

const client = new TriplitClient({
  serverUrl: 'https://<project-id>.triplit.io',
});

function onPageLoad() {
  // get the user's token from your authentication provider
  const token = await auth.getToken({ skipCache: true });
  if (token) {
    if (client.token) {
      await client.endSession();
    }
    await client.startSession(token);
  }
}
```

Connections to the server are managed with the Sessions API. Read more about it [here](/auth/sessions).

### Add permissions to your schema

Access control to data on a Triplit server is defined by permissions in the schema. Permissions can reference the JWT claims that are passed to Triplit. Once you've added permissions, you need to run `npx triplit schema push` to have them take effect on a deployed server (or just restart the development server if you're running it locally.).

```typescript filename="schema.ts"
export const schema = S.Collections({
  blogPosts: {
    schema: S.Schema({
      id: S.Id(),
      title: S.String(),
      content: S.String(),
      authorId: S.String(),
    }),
    permissions: {
      authenticated: {
        read: { filter: [true] },
        insert: { filter: ['authorId', '=', '$token.sub'] },
        update: { filter: ['authorId', '=', '$token.sub'] },
        postUpdate: { filter: ['authorId', '=', '$token.sub'] },
        delete: { filter: ['authorId', '=', '$token.sub'] },
      },
    },
  },
});
```

These permissions will allow any authenticated user to read all blog posts, but only allow them to insert, update, and delete their own posts. Notice that permissions are _defined as query filters_. This means that a permissions can be as complex as a query, and use `or`, `exists` and other query operators. Permissions can also reference relationships and/or any of the JWT claims on the user's `$token`. In this case, we're using the `sub` claim to identify the user. This is the default claim that most authentication providers will use to identify the user.

### Use token claims when inserting or updating data

When Triplit is given a JWT token, it makes the decoded claims available through the `TriplitClient.vars.$token`. If your collections have fields that are set to identifiable information from the token, you can access it there and use it in your calls to `insert` or `update`.

Using the `blogPosts` example from above, you can set the `authorId` field to the user's `sub` claim when inserting a new post:

```typescript
import { TriplitClient } from '@triplit/client';
const client = new TriplitClient({
  serverUrl: 'https://<project-id>.triplit.io',
});

const token = await auth.getToken({ skipCache: true });

await client.startSession(token);
await client.insert('posts', {
  title: 'My first blog post',
  content: 'Hello world!',
  authorId: client.vars.$token.sub, // set the authorId to the user's id
});
```

### Add additional roles (optional).

Triplit has two default roles: `authenticated` and `anonymous`. The `authenticated` role is used for any user that connect with a JWT that has a `sub` claim. The `anonymous` role is assigned to any client that connects with the Triplit-generated `anon` token. This is a special token that is safe to use on the client side and should be used when no user is logged in.

You may find that you need to create additional roles for your application. For example, you may have an admin role that is distinct from a normal user. See the [permissions guide](/schemas/permissions) for more information.

</Steps>

## Debugging authentication

If you are having trouble connecting to the server, there are a few things to try:

- pass the `logLevel: 'debug'` option to the `TriplitClient` constructor to get more information about the connection process and failures.
- confirm that your `serverUrl` is correct and that the server is running.
- check that the JWT being issued by your authentication provider is valid and has not expired. You can use [jwt.io](https://jwt.io/) to decode the JWT and check its claims.
- check that the your Triplit server is configured to accept the JWT. If you're using a third-party authentication provider, make sure that the public key or secret is set correctly in your Triplit server. If you're using a self-hosted server, make sure that the `EXTERNAL_JWT_SECRET` environmental variable is set.

```

```
